package presenter.code;

import main.InputBean;
import utils.OnLogListener;
import presenter.code.entity.AccountEntity;
import presenter.code.entity.AccountType;
import presenter.code.entity.CodeEntity;
import presenter.code.entity.CodeType;
import utils.FileBean;
import utils.*;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;

public class CodeParser {
    private final String rootPath;
    private final OnLogListener listener;
    private final List<AccountEntity> accounts = new ArrayList<>();

    public static void parse(InputBean info, OnLogListener listener) {
        new CodeParser(info.path1(), listener);
    }

    private CodeParser(String rootPath, OnLogListener listener) {
        this.rootPath = rootPath;
        this.listener = listener;
        ThreadPool.work(() -> filter(() -> sort(() -> print(() -> excel(listener::taskFinish)))));
    }

    //过滤有效文件
    private void filter(Runnable next) {
        log("解析开始!");
        List<FileBean> logs = FileFilter.filter(false, rootPath, name -> name.endsWith(".log"));
        if (logs == null || logs.isEmpty()) {
            log("未发现有效的logs文件夹");
            listener.taskFinish();
        } else {
            for (FileBean bean : logs) {
                AccountEntity account = parseAccount(bean);
                if (account.validAccount()) {
                    accounts.add(account);
                }
            }
            next.run();
        }
    }

    //排序一下
    private void sort(Runnable next) {
        Collections.sort(accounts);
        next.run();
    }

    //打印Account
    private void print(Runnable next) {
        for (AccountEntity account : accounts) {
            log(account.show());
        }
        next.run();
    }

    //打印Excel
    private void excel(Runnable next) {
        new ExcelCreator().create(rootPath, "自动汇总表.xls", accounts, new ExcelCreator.ExcelListener() {
            @Override
            public void onStart() {
                log("Excel导出中....");
            }

            @Override
            public void onSuccess() {
                log("Excel导出成功!");
                next.run();
            }

            @Override
            public void onError(String msg) {
                listener.log(msg);
                next.run();
            }
        });
    }

    private AccountEntity parseAccount(FileBean bean) {
        AccountEntity account = new AccountEntity();
        String path = bean.path();
        account.setPath(path);
        InputStreamReader isr = null;
        BufferedReader reader = null;
        try {
            List<CodeEntity> codes = new ArrayList<>();
            isr = new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8);
            reader = new BufferedReader(isr);
            String line;
            while ((line = reader.readLine()) != null) {
                List<CodeEntity> lineItems = parse(line);
                if (!lineItems.isEmpty()) {
                    codes.addAll(lineItems);
                }
                Triple<String, String, Boolean> accountAndLoginTime = parseLogin(line);
                if (accountAndLoginTime != null) {
                    account.set(accountAndLoginTime.getFirst(), accountAndLoginTime.getSecond(), accountAndLoginTime.getThird());
                }
            }
            account.set(codes);
        } catch (Exception ex) {
            //ignore
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (isr != null) {
                    isr.close();
                }
            } catch (Exception ex) {
                //ignore
            }
        }
        return account;
    }

    private Triple<String, String, Boolean> parseLogin(String line) {
        if (!TextUtils.isEmpty(line)) {
            for (AccountType type : AccountType.values()) {
                Matcher matcher = type.pattern().matcher(line);
                if (matcher.find()) {
                    String account = type.index(matcher);
                    Pair<String, Boolean> login = type.login(matcher);
                    return new Triple<>(account, login.getKey(), login.getValue());
                }
            }
        }
        return null;
    }

    private List<CodeEntity> parse(String line) {
        List<CodeEntity> lineResult = new ArrayList<>();
        if (!TextUtils.isEmpty(line)) {
            CodeEntity codeEntity = parseLine(line);
            if (codeEntity != null) {
                lineResult.add(codeEntity);
            }
        }
        return lineResult;
    }

    private CodeEntity parseLine(String line) {
        for (CodeType type : CodeType.values()) {
            Matcher matcher = type.pattern().matcher(line);
            if (matcher.find()) {
                Pair<String, Boolean> time = type.time(matcher);
                Pair<String, Boolean> stamp = type.stamp(matcher);
                return new CodeEntity(type.code(matcher), time.getKey(), time.getValue(), stamp.getKey(), stamp.getValue());
            }
        }
        return null;
    }

    private void log(String content) {
        listener.log(content);
    }
}
